package serverClientDemo;

import java.net.*;
import java.util.*;

/**
 * Client sends and receives messages to the server
 */

public class Client extends Observable {

	DatagramSocket socket;
	MessageReceiveThread thread;
	int listeningPort;

	/**
	 * Creates a new Client
	 */
	public Client() {
		try {
			socket = new DatagramSocket(1234);
			listeningPort = socket.getPort();
			thread = new MessageReceiveThread(this, socket);
			thread.start();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public boolean setPort(int port) {
		if (port < 1)
			return false;
		try {
			socket = new DatagramSocket(port);
			listeningPort = port;
			return true;
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
	}

	/**
	 * Change the listening port
	 * 
	 * @return
	 */
	public int getPort() {
		listeningPort = socket.getLocalPort();
		return listeningPort;
	}

	/**
	 * Sends a message
	 * 
	 * @param message
	 *            the message
	 * @return true if successful, false otherwise
	 */
	public boolean sendMessage(String address, int port, String message) {
		try {
			InetAddress serverAddress = InetAddress.getByName(address);
			int serverPort = port;
			byte[] data = message.getBytes();
			DatagramPacket packet = new DatagramPacket(data, data.length,
					serverAddress, serverPort);
			socket.send(packet);
			return true;
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
	}

	/**
	 * Waits for messages and notifies the client when messages are received
	 * 
	 * @author Chris
	 */
	private class MessageReceiveThread extends Thread {
		DatagramSocket socket;
		Client parent;

		public MessageReceiveThread(Client client, DatagramSocket socket) {
			this.socket = socket;
			this.parent = client;
		}

		public void run() {
			DatagramPacket packet = new DatagramPacket(new byte[1024], 1024);
			while (true) {
				try {
					socket.receive(packet);
					byte data[] = packet.getData();
					String message = new String(data);
					setChanged();
					parent.receivedMessage(message);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
	}

	/**
	 * Used by the thread to notify client that messages were received
	 * 
	 * @param message
	 *            the message
	 */
	public void receivedMessage(String message) {
		notifyObservers(message);
	}
}
